<script>
import { defineComponent, computed } from 'vue';
import { createNamespace, transformSize, transformStyleSize } from '../utils';

import FanLoading from '../loading/loading.vue';
import FanIcon from '../icon/icon.vue';

export default defineComponent({
  name: createNamespace('Button')[0],
  options: {
    // https://uniapp.dcloud.io/matter.html#mp
    virtualHost: true,
  },
  components: { FanLoading, FanIcon },
  emits: ['click', 'getphonenumber'],
  props: {
    color: String,
    bg: String,
    width: String,
    height: String,
    margin: String,
    padding: String,
    flex1: {
      type: Boolean,
      default: false,
    },
    textSize: {
      type: [String, Number],
    },
    textColor: String,
    bold: [Boolean, Number, String],
    /**
     * 图标或图片链接，同 Icon 组件的 name属性
     */
    icon: String,
    /**
     * 图标/loading的大小
     * @default textSize
     */
    iconSize: [String, Number],
    iconPosition: {
      type: String,
      validator: (value) => ['left', 'right'].includes(value),
      default: 'left',
    },
    // 图标与文字的间距
    iconPad: [String, Number],
    /**
     * 是否为块级元素
     */
    block: {
      type: Boolean,
      default: false,
    },
    /**
     * 是否为朴素按钮
     */
    plain: {
      type: Boolean,
      default: false,
    },
    /**
     * 是否有边框，plain朴素按钮时生效
     */
    border: {
      type: Boolean,
      default: true,
    },
    round: {
      type: Boolean,
      default: false,
    },
    /**
     * 圆角
     */
    radius: [String, Number],
    disabled: {
      type: Boolean,
      default: false,
    },
    /**
     * 是否使用 0.5px 边框
     */
    hairline: {
      type: Boolean,
      default: false,
    },
    loading: {
      type: Boolean,
      default: false,
    },
    loadingText: String,
    // 同 Loading 组件的 type属性
    loadingType: {
      type: String,
      default: 'circle2',
    },
    // 开放能力，目前仅非H5有效，同 https://uniapp.dcloud.io/component/button.html
    openType: String,
  },
  setup(props, context) {
    const theStyle = computed(() => {
      const {
        color,
        bg: _bg,
        plain,
        textSize,
        textColor,
        bold,
        round,
        radius,
        iconPad,
      } = props;
      const obj = {};
      ['width', 'height', 'padding', 'margin'].forEach(
        (k) => props[k] && (obj[k] = props[k]),
      );

      const bg = _bg || (plain ? 'transparent' : color);
      if (bg) obj['--fan-btn-bg'] = bg;

      const c =
        textColor ||
        (plain ? color || 'var(--fan-primary-color)' : !color ? '' : 'white');
      if (c) obj['--fan-btn-text-color'] = c;
      if (textSize) obj.fontSize = transformSize(textSize);
      if (iconPad) obj['--fan-btn-icon-pad'] = transformSize(iconPad);

      if (
        (typeof bold === 'number' || typeof bold === 'string') &&
        Number(bold) >= 100
      ) {
        obj.fontWeight = bold;
      }

      // 可以考虑用TinyColor.tint(20)对非css-var颜色的border浅色一下
      if (plain && color) obj['--fan-btn-border-color'] = color;

      if (radius || radius === 0) obj['--fan-btn-border-radius'] = radius;
      else if (round) obj['--fan-btn-border-radius'] = 'var(--fan-radius-max)';
      return transformStyleSize(obj);
    });
    const theIconSize = computed(() => {
      return props.iconSize || props.textSize;
    });
    const theIconPosition = computed(() => {
      const { icon, iconPosition, loading } = props;
      if (loading) return 'left';
      if (!icon) return 'none';
      return iconPosition;
    });
    const showText = computed(() => {
      const { loading, loadingText } = props;
      // #ifndef MP-ALIPAY
      // 支付宝小程序 slots.default 始终为 undefined，此操作遗留问题：一个图标按钮没有文字时图标可能不居中
      // uniapp 最新版本已修复，待验证——20220922
      return context.slots.default && (!loading || !loadingText);
      // #endif
      return !loading || !loadingText;
    });

    const onClick = (e) => {
      context.emit('click', e);
    };

    // openType为getPhoneNumber时触发
    const getPhoneNumber = (e) => {
      context.emit('getphonenumber', e);
    };

    return {
      theStyle,
      theIconSize,
      theIconPosition,
      showText,
      onClick,
      getPhoneNumber,
    };
  },
});
</script>

<template>
  <button
    class="fan-btn"
    :class="{
      'fan-btn--f1': flex1,
      'fan-btn--block': block,
      'fan-btn--disabled': disabled,
      'fan-btn--noborder': !border,
      'fan-btn--hairline': hairline,
      'fan-btn--plain': plain,
      'fan-btn--bold': bold,
    }"
    hover-class="none"
    :style="theStyle"
    :disabled="disabled"
    :open-type="openType"
    @click="onClick"
    @getphonenumber="getPhoneNumber"
  >
    <!-- fix：uniapp-App-伪元素超不出100% -->
    <div v-if="hairline" class="fan-btn__hairline"></div>
    <FanLoading
      v-if="loading"
      color="currentColor"
      :type="loadingType"
      :size="theIconSize"
      :text-size="textSize"
      text-color="inherit"
      >{{ loadingText }}</FanLoading
    >
    <FanIcon
      v-if="theIconPosition === 'left'"
      :name="icon"
      color="currentColor"
      :size="theIconSize"
    />
    <div
      v-if="showText"
      class="fan-btn__in"
      :class="[`fan-btn--i${theIconPosition}`]"
    >
      <slot />
    </div>
    <FanIcon
      v-if="theIconPosition === 'right'"
      :name="icon"
      color="currentColor"
      :size="theIconSize"
    />
  </button>
</template>

<style lang="less">
.fan-btn {
  --fan-btn-bg: var(--fan-primary-color);
  --fan-btn-text-color: var(--fan-primary-fg-color);
  --fan-btn-border-color: var(--fan-primary-color);
  --fan-btn-border-radius: 2px;
  --fan-btn-icon-pad: 4px;

  display: inline-flex;
  justify-content: center;
  align-items: center;
  height: 40px;
  margin: 0;
  padding: 0 15px;
  font-size: 14px;
  color: var(--fan-btn-text-color);
  background: var(--fan-btn-bg);
  border-radius: var(--fan-btn-border-radius);
  border: 0;
  outline: none;
  box-sizing: border-box;
  // #ifdef H5
  &[disabled]:not([type]) {
    color: var(--fan-btn-text-color);
    background: var(--fan-btn-bg);
  }
  // #endif
  &::after {
    display: none;
  }

  &:active {
    opacity: var(--fan-active-opacity);
  }

  & + .fan-btn {
    margin-left: 10px;
  }

  &--block {
    display: flex;
    width: 100%;
    width: -moz-available;
    width: -webkit-fill-available;

    // width: fill-available; stretch?
    & + .fan-btn {
      margin-left: 0;
    }
  }

  &--f1 {
    flex: 1;
  }

  &--plain {
    --fan-btn-border-color: var(--fan-primary-color-8);
    border: 1px solid var(--fan-btn-border-color);
  }

  &--bold {
    font-weight: var(--fan-text-mbold);
  }

  &--disabled {
    opacity: 0.5 !important;
    opacity: var(--fan-disabled-opacity) !important;
    cursor: not-allowed;
  }

  &--noborder {
    border: 0;
    background: transparent;

    .fan-btn__hairline {
      display: none;
    }
  }

  &--hairline {
    border: 0;
    overflow: visible;
    position: relative;

    .fan-btn__hairline {
      pointer-events: none;
      position: absolute;
      top: -50%;
      left: -50%;
      right: -50%;
      bottom: -50%;
      border: 1px solid var(--fan-btn-border-color);
      border-radius: calc(var(--fan-btn-border-radius) * 2);
      transform: scale(0.5);
    }
  }

  &--ileft {
    margin-left: var(--fan-btn-icon-pad);
  }

  &--iright {
    margin-right: var(--fan-btn-icon-pad);
  }
}
</style>
